#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include "../modbus/create_modbus_custom_slave.h"
#include "SqliteInterface.h"
#include "logRecordFunction.h"

bool glb_upper_connect_flag = false;
static int packNum = 0;
#define LOG_SQL_TABLE  "LogRecordTable"

static int upperCallback(void *buf, int argc, char **argv, char **azColName){
    /*YYYY-MM-DD HH:MM:SS.sss*/
    char year[5], month[3], day[3], hour[3], minute[3], second[3], millisecond[4];  // 修改毫秒部分的大小
    uint8_t* rsp = (uint8_t*) buf;

    for (int i = 0; i < argc; i++) {
        // printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
        if (strcmp(azColName[i], "FuncMainType") == 0) {
            rsp[packNum++] = atoi(argv[i]);
        }
        if (strcmp(azColName[i], "FuncSubType") == 0) {
            uint16_t subType = atoi(argv[i]);
            rsp[packNum++] = (uint8_t)((subType >> 8) & 0xFF);  // 保存高 8 位
            rsp[packNum++] = (uint8_t)(subType & 0xFF);  // 保存低 8 位  

        }
        if (strcmp(azColName[i], "TimeStamp") == 0) {
            sscanf(argv[i], "%4s-%2s-%2s %2s:%2s:%2s.%3s", year, month, day, hour, minute, second, millisecond);  // 添加毫秒部分的解析
            uint16_t value = atoi(year);
            rsp[packNum++] = (uint8_t)((value >> 8) & 0xFF);  // 保存高 8 位
            rsp[packNum++] = (uint8_t)(value & 0xFF);  // 保存低 8 位
            rsp[packNum++] = atoi(month);
            rsp[packNum++] = atoi(day);
            rsp[packNum++] = atoi(hour);
            rsp[packNum++] = atoi(minute);
            rsp[packNum++] = atoi(second);

            // 解析毫秒部分并转换为整数
            uint16_t milliseconds = atoi(millisecond);
            rsp[packNum++] = (uint8_t)((milliseconds >> 8) & 0xFF);  // 保存高 8 位
            rsp[packNum++] = (uint8_t)(milliseconds & 0xFF);  // 保存低 8 位
        } 
    }

    return 0;
}


void getTimestamp(char *timestamp, int *ms) {
    struct timeval tv;
    gettimeofday(&tv, NULL);

    *ms = (int) (tv.tv_usec / 1000);
    long long milliseconds = (long long) tv.tv_sec * 1000LL + tv.tv_usec / 1000;
    // 转换为本地时间
    time_t seconds = (time_t) (milliseconds / 1000);
    struct tm timeinfo;
    localtime_r(&seconds, &timeinfo);  // 使用 localtime_r 函数

    // 格式化成字符串
    strftime(timestamp, 30, "%Y-%m-%d %H:%M:%S", &timeinfo);


    // 追加毫秒部分
    //ms = (int) (tv.tv_usec % 1000);
    sprintf(timestamp + strlen(timestamp), ".%03d", *ms);
    //printf("timestamp = %s \n",timestamp);

}

void getSpecificTimestamp(char *timestamp) {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    //printf("-------------xujinyoudebug  [%s(%d)]-------\n",__func__, __LINE__);
    long long milliseconds = (long long) tv.tv_sec * 1000LL + tv.tv_usec / 1000;
    // 转换为本地时间
    time_t seconds = (time_t) (milliseconds / 1000);
    struct tm timeinfo;
    localtime_r(&seconds, &timeinfo);  // 使用 localtime_r 函数

    // 设置时分秒为0
    timeinfo.tm_hour = 0;
    timeinfo.tm_min = 0;
    timeinfo.tm_sec = 0;

    // 格式化成字符串
    strftime(timestamp, 30, "%Y-%m-%d %H:%M:%S", &timeinfo);

    // 追加毫秒部分
    int ms = 0;  // 将毫秒部分设置为0
    sprintf(timestamp + strlen(timestamp), ".%03d", ms);
    //printf("-------------xujinyoudebug  [%s(%d)]-------\n",__func__, __LINE__);
}

void setSpecificTimestamp(uint8_t *inputTime, char *timestamp) {

    for(int i = 0;i<4;i++){
        //time[i] = req[i+9];
        printf("xujinyou-debug  time[i] = %d\n",inputTime[i]);
    }
    int year = ((inputTime[0] << 8) + inputTime[1]) & 0xFFF; // 获取年份
    int month = inputTime[2]; // 获取月份
    int day = inputTime[3]; // 获取日期

    struct tm timeinfo = {0};
    timeinfo.tm_year = year - 1900;  // 年份需要减去1900
    timeinfo.tm_mon = month - 1; 
    timeinfo.tm_mday = day;

    // 设置时分秒为0
    timeinfo.tm_hour = 0;
    timeinfo.tm_min = 0;
    timeinfo.tm_sec = 0;

    // 将时间转换为秒数
    //time_t seconds = mktime(&timeinfo);

    // 格式化成字符串
    strftime(timestamp, 30, "%Y-%m-%d %H:%M:%S", &timeinfo);
    printf(" 上位机查询 [%s] 当日日志！\n", timestamp);
    // 追加毫秒部分
    sprintf(timestamp + strlen(timestamp), ".000");
}

int queryByTime_db(uint8_t* time, uint8_t *rsp){
    char *zErrMsg = 0;
    int rc;
    char sql[300];
    int length = 0;
    static char start_timestamp[30];
    static char end_timestamp[30];
    setSpecificTimestamp(time, start_timestamp);
    time[3] = time[3] + 1;
    setSpecificTimestamp(time, end_timestamp);
    sprintf(sql, "SELECT * FROM %s WHERE LogType = 1 AND datetime(TimeStamp) > datetime('%s') AND datetime(TimeStamp) < datetime('%s');",\
    LOG_SQL_TABLE, start_timestamp, end_timestamp);

    //printf("----------------------sql--------------- = %s\n", sql);
    rc = sqlite3_exec(db, sql, upperCallback, rsp, &zErrMsg);
    //printf("----------------------rc--------------- = %d\n", rc);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }

    length = packNum;
    packNum = 0; //需重置回0

    return length;
}

int insertLog_db(LogClassData* logClassData) {
    int ret;
    sqlite3_stmt *stmt = NULL;
    char timestamp[30];
    int timeMs;

    getTimestamp(timestamp,&timeMs);
    const char *sql = "INSERT INTO %s (LogType, FuncMainType, FuncSubType, DataType, Data, TimeStamp, TimeMs) VALUES (?, ?, ?, ?, ?, ?, ?)";
    sql = sqlite3_mprintf(sql, LOG_SQL_TABLE);
    ret = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
    sqlite3_free((void*)sql);

    if (ret != SQLITE_OK) {
        printf("[%s(%d)] sqlite3_prepare_v2 error - %s\n", __func__, __LINE__, sqlite3_errmsg(db));
        return ret;
    }

    sqlite3_bind_int(stmt, 1, logClassData->logType);
    sqlite3_bind_int(stmt, 2, logClassData->logFuncMainType);
    sqlite3_bind_int(stmt, 3, logClassData->logFuncSubType);
    sqlite3_bind_int(stmt, 4, logClassData->logDataType);
    sqlite3_bind_int(stmt, 7, timeMs);
    switch (logClassData->logDataType) {
        case COM_DATA_TYPE_UINT8:
            sqlite3_bind_int(stmt, 5, logClassData->logDataValue.uint8Value);
            break;
        case COM_DATA_TYPE_INT8:
            sqlite3_bind_int(stmt, 5, logClassData->logDataValue.int8Value);
            break;
        case COM_DATA_TYPE_UINT16:
            sqlite3_bind_int(stmt, 5, logClassData->logDataValue.uint16Value);
            break;
        case COM_DATA_TYPE_INT16:
            sqlite3_bind_int(stmt, 5, logClassData->logDataValue.int16Value);
            break;
        case COM_DATA_TYPE_UINT32:
            sqlite3_bind_int(stmt, 5, logClassData->logDataValue.uint32Value);
            break;
        case COM_DATA_TYPE_INT32:
            sqlite3_bind_int(stmt, 5, logClassData->logDataValue.int32Value);
            break;
        case COM_DATA_TYPE_UINT64:
            sqlite3_bind_int64(stmt, 5, logClassData->logDataValue.uint64Value);
            break;
        case COM_DATA_TYPE_INT64:
            sqlite3_bind_int64(stmt, 5, logClassData->logDataValue.int64Value);
            break;
        case COM_DATA_TYPE_FLOAT:
            sqlite3_bind_double(stmt, 5, logClassData->logDataValue.floatValue);
            break;
        default:
            sqlite3_bind_null(stmt, 5);
            break;
    }

    sqlite3_bind_text(stmt, 6, timestamp, -1, SQLITE_TRANSIENT);

    ret = sqlite3_step(stmt);
    if (ret != SQLITE_DONE) {
        printf("[%s(%d)] sqlite3_step error - %s\n", __func__, __LINE__, sqlite3_errmsg(db));
    }else {
        // fprintf(stdout, "Data inserted successfully\n");
    }

    sqlite3_finalize(stmt);
    return SQLITE_OK;
}

int deleteLog_db(LogClassData* logClassData){
    char *zErrMsg = 0;
    int rc;
    
    char sql[300];
    sprintf(sql, "DELETE * FROM %s WHERE LogType = %d AND FuncMainType = %d;", LOG_SQL_TABLE,logClassData->logType, logClassData->logFuncMainType);
   
    rc = sqlite3_exec(db, sql, upperCallback, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } else {
        fprintf(stdout, "Data deleted successfully\n");
    }
    return 0;
}

int updateLog_db() {
    char *err_msg = 0;
    
    // 检查数据量是否超过10000条
    sqlite3_stmt *stmt;
    //char *count_sql = "SELECT COUNT(*) FROM LogRecordTable WHERE id IS NOT NULL;";
    char *count_sql = "SELECT COUNT(*) FROM LogRecordTable;";
    int rc = sqlite3_prepare_v2(db, count_sql, -1, &stmt, 0);
    
    if (rc != SQLITE_OK) {
        fprintf(stderr, "SQL错误: %s\n", sqlite3_errmsg(db));
        return -1;
    }
    
    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW) {
        int count = sqlite3_column_int(stmt, 0);      
        if (count > 10000) {
            // 计算需要删除的记录数量 
            int delete_count = count - 10000;

            // 删除最早插入的记录（按照id顺序）
            char delete_sql[150];
            snprintf(delete_sql, 150, "DELETE FROM LogRecordTable WHERE Timestamp IN (SELECT Timestamp FROM LogRecordTable ORDER BY Timestamp ASC LIMIT %d);", delete_count);
            //snprintf(delete_sql, 120, "DELETE FROM LogRecordTable WHERE id IN (SELECT id FROM LogRecordTable ORDER BY id  LIMIT 100);");

            rc = sqlite3_exec(db, delete_sql, 0, 0, &err_msg);
            if (rc != SQLITE_OK ) {
                fprintf(stderr, "SQL错误: %s\n", err_msg);
                sqlite3_free(err_msg);
                return -1;
            } else {
                fprintf(stdout, "删除前%d条记录成功\n", delete_count);
            }
        }
    } else {
        fprintf(stderr, "没有获取到查询结果\n");
        return -1;
    }
    //sqlite3_wal_checkpoint(db,"LogRecordTable");
    sqlite3_finalize(stmt); // 释放准备语句对象
    return 0;
}

int readLog_db(LogClassData* logClassData){

    char *zErrMsg = 0;
    int rc;
    
    char sql[300];
    sprintf(sql, "SELECT * FROM %s WHERE LogType = %d AND FuncMainType = %d;", LOG_SQL_TABLE,logClassData->logType, logClassData->logFuncMainType);
   
    rc = sqlite3_exec(db, sql, upperCallback, 0, &zErrMsg);
    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    } else {
        // fprintf(stdout, "Data retrieved successfully\n");
    }
    return 0;
}

int queryByTypes_db(LogClassData* logClassData, uint8_t *rsp){
    char *zErrMsg = 0;
    int rc;
    char sql[300];
    int length = 0;
    static char current_timestamp[30];
    static int curMs;    
    //printf("-------------xujinyoudebug  [%s(%d)]-------\n",__func__, __LINE__);
    if(glb_upper_connect_flag){
        sprintf(sql, "SELECT  * FROM %s WHERE LogType = %d AND (datetime(TimeStamp) > datetime('%s') OR (datetime(TimeStamp) == datetime('%s') AND TimeMs > %d) );",\
        LOG_SQL_TABLE, logClassData->logType, current_timestamp, current_timestamp, curMs);

    }else{
        getSpecificTimestamp(current_timestamp);
        sprintf(sql, "SELECT * FROM %s WHERE LogType = %d AND datetime(TimeStamp) > datetime('%s') ;", LOG_SQL_TABLE,logClassData->logType, current_timestamp);
        glb_upper_connect_flag = true;
    }
    //printf("----------------------sql--------------- = %s\n", sql);
    getTimestamp(current_timestamp,&curMs);
    rc = sqlite3_exec(db, sql, upperCallback, rsp, &zErrMsg);

    if( rc != SQLITE_OK ){
        fprintf(stderr, "SQL error: %s\n", zErrMsg);
        sqlite3_free(zErrMsg);
    }

    length = packNum;
    packNum = 0; //需重置回0

    return length;
}
